package com.qys.livesMall.shop.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.qys.livesMall.app.user.service.IH2AppUserService;
import com.qys.livesMall.common.constants.Constants;
import com.qys.livesMall.common.exception.QysException;
import com.qys.livesMall.common.message.MessageServer;
import com.qys.livesMall.common.result.R;
import com.qys.livesMall.common.utils.MessageUtils;
import com.qys.livesMall.finance.enums.AccountBusinessTypeEnum;
import com.qys.livesMall.finance.model.dto.FinancePayDTO;
import com.qys.livesMall.finance.service.FinanceBusinessService;
import com.qys.livesMall.finance.util.BusinessNoUtil;
import com.qys.livesMall.framework.utils.SecurityUtils;
import com.qys.livesMall.framework.utils.SnowflakeGenerator;
import com.qys.livesMall.product.entity.H2ProductGoodsinfo;
import com.qys.livesMall.product.entity.H2ProductSku;
import com.qys.livesMall.product.service.H2ProductGoodsinfoService;
import com.qys.livesMall.product.service.H2ProductSkuService;
import com.qys.livesMall.shop.constants.ShopConstant;
import com.qys.livesMall.shop.dao.H2ShopBaseDao;
import com.qys.livesMall.shop.enums.ShopMessageEnum;
import com.qys.livesMall.shop.mapper.ShopPurchaseInfoMapper;
import com.qys.livesMall.shop.mapper.ShopPurchaseSkuMapper;
import com.qys.livesMall.shop.modal.dto.PurchaseAccountUse;
import com.qys.livesMall.shop.modal.dto.PurchaseSku;
import com.qys.livesMall.shop.modal.dto.shop.AppPurchase;
import com.qys.livesMall.shop.modal.entity.*;
import com.qys.livesMall.shop.service.*;
import com.qys.livesMall.system.model.entity.H2SysConfig;
import com.qys.livesMall.system.service.IH2SysConfigService;
import jakarta.annotation.Resource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author guomx
 * @since 2023-06-06
 */
@Service
public class ShopPurchaseInfoServiceImpl extends ServiceImpl<ShopPurchaseInfoMapper, ShopPurchaseInfo> implements ShopPurchaseInfoService {
    @Resource
    ShopPurchaseInfoMapper infoMapper;
    @Resource
    ShopPurchaseSkuMapper skuMapper;
    @Resource
    H2ProductGoodsinfoService GoodsinfoService;
    @Resource
    H2ProductGoodsinfoService productInfoService;
    @Resource
    H2ProductSkuService productSkuService;
    @Resource
    ShopPurchaseService purchaseService;
    @Resource
    ShopGoodsInfoService shopGoodsInfoService;
    @Resource
    ShopGoodsSkuService shopGoodsSkuService;
    @Resource
    private H2ShopBaseDao h2ShopBaseDao;

    @Resource
    private ShopGoodsSkuStocksService stocksService;
    @Resource
    private IH2SysConfigService configService;

    @Resource
    private FinanceBusinessService financeBusinessService;

    @Resource
    private MessageServer messageServer;

    @Autowired
    private ShopIncomeConfigService shopIncomeConfigService;

    @Autowired
    private H2ShopLevelService shopLevelService;

    @Autowired
    private IH2AppUserService userService;

    @Autowired
    private ShopPurchaseAccountService shopPurchaseAccountService;

    @Autowired
    private PurchaseCartService purchaseCartService;

    private final Map<Long, Object> locks = new ConcurrentHashMap<>();



    @Override
    @Transactional(rollbackFor={Exception.class})
    public R addList(AppPurchase purchase) {
        H2SysConfig config = configService.getConfigByKey("2d06122ab76a4d2d9ed8928da49b500e");


        if (ObjectUtils.isEmpty(config))return R.fail("system error");
        String val = config.getValue();
        LocalDateTime now = LocalDateTime.now();
        H2ShopBase shopBase=h2ShopBaseDao.getByUserId(SecurityUtils.getUserId());
        if (shopBase==null||!Objects.equals(shopBase.getStatus(), ShopConstant.ShopStatus.IN_BUSINESS)){
            return messageServer.failMsg(ShopMessageEnum.SHOP_NOT_EXIST);
        }
//        不是水军 校验支付密码
        if(!purchase.getNavyUser()){
            boolean isPassword =userService.checkUserPayPassword(SecurityUtils.getUserId().toString(),purchase.getPassword());
            if (!isPassword) return R.fail(MessageUtils.message("shop.password.error"));
        }
        //
        H2ShopLevel level=shopLevelService.getById(shopBase.getShopLevelId());

        List<PurchaseSku> skus = purchase.getSkus();
        long snowID = SnowflakeGenerator.generateSnowflakeID(1L);
        String afterId = String.valueOf(snowID);
        String id = "1" + afterId;
        String message ="";
        //创建采购单
        ShopPurchaseInfo info =new ShopPurchaseInfo();
        info.setId(Long.valueOf(id));
        info.setShopId(purchase.getShopId());
        Integer totalNum=purchase.getSkus().stream().filter(Objects::nonNull).map(PurchaseSku::getNum).reduce(0, Integer::sum);
        info.setTotalNum(totalNum);
        info.setPayType(purchase.getPayType());
        info.setPayStatus(purchase.getPayType());
        info.setCreateTime(LocalDateTime.now());
        info.setUpdateTime(LocalDateTime.now());
        int infoRow = infoMapper.insert(info);
        if (infoRow<1)throw new QysException(MessageUtils.message("create.shop.order.error"));

        BigDecimal totalMoneys = BigDecimal.ZERO;
        BigDecimal actualTotalMoneys = BigDecimal.ZERO;

        Map<Long,ShopGoodsInfo> shopGoodsMap=new HashMap<>();

        BigDecimal discountRatio =new BigDecimal("1");

        if(Objects.equals(Constants.YesNo.YES,purchase.getPayType())){
            //优惠比例
            //String ratio=configService.getConfigKey("0733980a140b45d19633aaa8042bfa26");
            BigDecimal ratio=shopIncomeConfigService.getAdvancePaymentConfig();
            if (ratio!=null){
                discountRatio=ratio;
            }
        }
        for (PurchaseSku purchaseSku:skus){
            //获取商品
            H2ProductSku productSku=productSkuService.getById(purchaseSku.getSkuId());
            if (productSku==null){
                throw new QysException(MessageUtils.message("not.find.goods"));
            }

            if (purchaseSku.getNum()<level.getPurchaseMinNum()){
                throw new QysException(ShopMessageEnum.NOT_LESS_MIN_PURCHASE_NUM);
            }

            //创建采购明细
            ShopPurchaseSku shopPurchaseSku = new ShopPurchaseSku();
            shopPurchaseSku.setGoodsId(productSku.getSpuId());
            shopPurchaseSku.setSkuId(productSku.getId());
            shopPurchaseSku.setName(productSku.getName());

            shopPurchaseSku.setNum(purchaseSku.getNum());
            shopPurchaseSku.setOrderId(Long.valueOf(id));
            //原单价
            shopPurchaseSku.setPrice(productSku.getPrice());
            //实付单价
            shopPurchaseSku.setActualPrice(productSku.getPrice().multiply(discountRatio).setScale(4, RoundingMode.DOWN));
            //原总价
            BigDecimal money = shopPurchaseSku.getPrice().multiply(new BigDecimal(purchaseSku.getNum())).setScale(4, RoundingMode.DOWN);
            shopPurchaseSku.setMoney(money);
            //实付总价
            shopPurchaseSku.setActualPayAmount(shopPurchaseSku.getActualPrice().multiply(new BigDecimal(purchaseSku.getNum())).setScale(4, RoundingMode.DOWN));

            shopPurchaseSku.setImage(productSku.getImage());
            shopPurchaseSku.setShopId(info.getShopId().toString());
            shopPurchaseSku.setBusinessNo(BusinessNoUtil.get(AccountBusinessTypeEnum.PURCHASE));
            int skuRow = skuMapper.insert(shopPurchaseSku);
            if (skuRow<1){
                throw new QysException(MessageUtils.message("create.shop.order.error"));
            }
            //扣除库存
            synchronized (productSku.getId()){
                Integer num=productSku.getNum()-purchaseSku.getNum();
                if (num<0){
                    throw new QysException(MessageUtils.message("understock"));
                }
                productSku.setNum(num);
                productSkuService.updateById(productSku);
            }
            Integer sumNum=productSkuService.getBySpuId(productSku.getSpuId());
            totalMoneys=totalMoneys.add(money);
            actualTotalMoneys=actualTotalMoneys.add(shopPurchaseSku.getActualPayAmount());

            //创建商铺商品
            H2ProductGoodsinfo productGoods = GoodsinfoService.getById(productSku.getSpuId());
            productGoods.setNum(sumNum);
            GoodsinfoService.updateById(productGoods);
            ShopGoodsInfo shopGoods=shopGoodsMap.get(productGoods.getId());
            if (shopGoods==null){
                //查看店铺是否有商品信息
                LambdaQueryWrapper<ShopGoodsInfo> wrapper = new LambdaQueryWrapper<>();
                wrapper.eq(ShopGoodsInfo::getGoodsId,productGoods.getId());
                wrapper.eq(ShopGoodsInfo::getShopId,purchase.getShopId());
                wrapper.eq(ShopGoodsInfo::getIsDelete,1);
                ShopGoodsInfo old = shopGoodsInfoService.getOne(wrapper);
                if (ObjectUtils.isNotEmpty(old)){
                    shopGoods=old;
                }
            }
            if (shopGoods==null){
                shopGoods = new ShopGoodsInfo();
                shopGoods.setCreateTime(now);
            }
            shopGoodsMap.put(productGoods.getId(),shopGoods);
            //补充

            shopGoods.setShopId(purchase.getShopId());
            shopGoods.setGoodsId(productGoods.getId());
            shopGoods.setGoodsName(productGoods.getName());
            shopGoods.setCategoryOneId(productGoods.getCategoryOneId());
            shopGoods.setCategoryTwoId(productGoods.getCategoryTwoId());
            shopGoods.setGoodsDesc(productGoods.getIntro());
            shopGoods.setPrice(productGoods.getPrice());
            shopGoods.setOriginalPrice(productGoods.getPrice());
            shopGoods.setGoodsId(productGoods.getId());
            shopGoods.setImage(productGoods.getImage());
            shopGoods.setImages(productGoods.getImages());
            shopGoods.setIsDelete("1");
            shopGoods.setUpdateTime(now);
            shopGoods.setUpShelfDate(now);
            shopGoods.setStatus(false);
            if(!shopGoodsInfoService.saveOrUpdate(shopGoods)) throw new QysException(MessageUtils.message("create.shop.goods.error"));
            shopGoodsInfoService.upDown(shopGoods.getId(),true);
            //库存
            //商铺是否存在sku
            LambdaQueryWrapper<ShopGoodsSku> goodsSkuqueryWrapper = new LambdaQueryWrapper<>();
            goodsSkuqueryWrapper.eq(ShopGoodsSku::getSkuId,productSku.getId());
            goodsSkuqueryWrapper.eq(ShopGoodsSku::getShopGoodsId,shopGoods.getId());
            goodsSkuqueryWrapper.eq(ShopGoodsSku::getShopId,purchase.getShopId());
            ShopGoodsSku oldSku = shopGoodsSkuService.getOne(goodsSkuqueryWrapper);
            ShopGoodsSku shopGoodsSku =null;
            if (oldSku==null){
                shopGoodsSku=new ShopGoodsSku();
                shopGoodsSku.setShopId(purchase.getShopId());
                shopGoodsSku.setShopGoodsId(shopGoods.getId());
                shopGoodsSku.setGoodsId(shopGoods.getGoodsId());
                shopGoodsSku.setSkuId(productSku.getId());
                shopGoodsSku.setSkuName(productSku.getName());
                shopGoodsSku.setSkuAttr(productSku.getSkuAttribute());
                shopGoodsSku.setImage(productSku.getImage());
                shopGoodsSku.setPrice(productSku.getPrice());
                shopGoodsSku.setOriginalPrice(productSku.getPrice());
                if(!shopGoodsSkuService.save(shopGoodsSku)) throw new QysException(MessageUtils.message("create.shop.goods.error"));
            }else {
                shopGoodsSku=oldSku;
            }
            //商铺库存
            ShopGoodsSkuStocks stocks = new ShopGoodsSkuStocks();
            stocks.setNum(purchaseSku.getNum());
            stocks.setSkuId(shopGoodsSku.getId());
            stocks.setPrice(productSku.getPrice());
            stocks.setCostPrice(productSku.getPrice());
            stocks.setState(false);
            stocks.setPayType(purchase.getPayType());
            stocks.setCreateTime(LocalDateTime.now());
            stocks.setBusinessNo(shopPurchaseSku.getBusinessNo());
            stocks.setShopId(shopBase.getId());
            stocks.setPurchaseId(shopPurchaseSku.getId());
            if(!stocksService.save(stocks)) throw new QysException(MessageUtils.message("create.shop.goods.stocks.error"));

            //支付
            if(Objects.equals(Constants.YesNo.YES,purchase.getPayType())){
                FinancePayDTO dto = new FinancePayDTO();
                dto.setUserId(SecurityUtils.getUserId());
                dto.setShopId(purchase.getShopId());
                dto.setBusinessType(AccountBusinessTypeEnum.PURCHASE);
                dto.setAmountIncurred(shopPurchaseSku.getActualPayAmount());
                dto.setBusinessNo(shopPurchaseSku.getBusinessNo());
                financeBusinessService.pay(dto);
                if (!dto.getSuccess()) throw new QysException(dto.getMessage());
            }

            //清理采购购物车
            purchaseCartService.remove(Wrappers.<PurchaseCart>lambdaQuery().eq(PurchaseCart::getUserId, SecurityUtils.getUserId()).eq(PurchaseCart::getProductSkuId, purchaseSku.getSkuId()));
        }
        //扣除额度
        PurchaseAccountUse use=new PurchaseAccountUse();
        use.setUserId(shopBase.getUserId());
        use.setShopId(shopBase.getId());
        use.setUseAmount(totalMoneys);
        use.setPurchaseId(info.getId());
        shopPurchaseAccountService.purchaseOut(use);
        if (!use.isStatus()){
            throw new QysException(use.getMessage());
        }
        info.setMoneys(totalMoneys);
        info.setActualPayAmount(actualTotalMoneys);
        if(!super.updateById(info))throw new QysException("system error");
        if (message!="") throw new QysException(message);
        return R.ok();
    }


}
